package ctrl;

import net.rim.device.api.system.Bitmap;
import net.rim.device.api.system.Display;
import net.rim.device.api.system.EncodedImage;
import net.rim.device.api.system.KeypadListener;
import net.rim.device.api.ui.Graphics;
import net.rim.device.api.ui.TouchEvent;
import net.rim.device.api.ui.XYRect;
import net.rim.device.api.ui.component.BitmapField;

public class ScrollableImageField extends BitmapField
{
    private Bitmap _theImage;       //The image to display.
    private int _preferredHeight;   //The height the field request.
    private int _preferredWidth;    //The width the field requests.
    
    private int _xCoord = 0;         //The x coordinate for the top left corner of the image.
    private int _yCoord = 0;         //The y coordinate for the top left corner of the image.
    
    private int _xTouch = 0;		//The x coordinate of the previous touch point.
    private int _yTouch = 0;		//The y coordinate of the previous touch point.
    
    //public ScrollableImageField() {super();}
    
    public ScrollableImageField(Bitmap theImage) 
    {    
        super(theImage, BitmapField.FOCUSABLE);
        _theImage = theImage;
        calculateSize();
    }
    
    public ScrollableImageField(EncodedImage theImage)
    {
        this(theImage.getBitmap());
    }
    
    //Calculates the preferred width and height of the field and determines if the image should scroll. 
    private void calculateSize()
    {
        //Set the preferred height to the image size or screen height if the image is larger than the screen height.
    	_preferredHeight=_theImage.getHeight() > Display.getHeight() ? Display.getHeight() : _theImage.getHeight();  

        //Set the preferred width to the image size or screen width if the image is larger than the screen width.
    	_preferredWidth=_theImage.getWidth() > Display.getWidth() ? Display.getWidth() : _theImage.getWidth();
    }
    
    //Override setBitmap to perform new size calculations.
    public void setBitmap(Bitmap bitmap)
    {
        super.setBitmap(bitmap);
        updateLayout();
        //Reset the image location to display the top left of the image.
        _xCoord = 0;
        _yCoord = 0;
        
        _theImage = bitmap;
        calculateSize();

        updateLayout();
    }
    
    //Override setImage to perform new size calculations.
    public void setImage(EncodedImage image)
    {
        _theImage = image.getBitmap();
        //Reset the image location to display the top left of the image.
        
        _xCoord = 0;
        _yCoord = 0;
        
        this.setBitmap(_theImage);
        calculateSize();
    }
    
    public int getPreferredHeight() {return _preferredHeight;}
    
    public int getPreferredWidth() {return _preferredWidth;}
    
    protected void paint(Graphics graphics)
    {
        //Get the actual field size from its manager.
        XYRect rect = this.getManager().getContentRect();        
        
        //Draw the Bitmap, taking up the full size of the BitmapField.
        //Start drawing the bitmap at the current coordinates.        
        System.out.println("rect width: " + rect.width + "\nrect height: " + rect.height + "\nxCoord: " + _xCoord + "\nyCorrd: " + _yCoord);
        graphics.drawBitmap(0, 0, rect.width, rect.height, _theImage, _xCoord, _yCoord);
    }
    
    protected void drawFocus(Graphics graphics, boolean on) {}
    
    //Override navigationMovement to provide image scrolling.
    protected boolean navigationMovement(int dx, int dy, int status, int time)
    {
        //Alt + scroll bypasses scrolling within the field.
        if((status & KeypadListener.STATUS_ALT) != 0) {return super.navigationMovement(dx, dy, status, time);}
        
        System.out.println("dx moves: " + dx);
        if(scrollImage(dx*10, dy*10))
        {
        	//The image was scrolled and the movement consumed.
            return true;
        } else
        {
        	//Scrolling is not required.
            return super.navigationMovement(dx, dy, status, time);
        }       
    }
    
  	//Override touchEvent to provide image scrolling for touch screen devices.
    protected boolean touchEvent(TouchEvent touchEvent)
    {
    	int event = touchEvent.getEvent();
    	
    	//Populate the start coordinates of the touch event.
    	if (event == TouchEvent.DOWN && touchEvent.isValid())
    	{
    		_xTouch = touchEvent.getX(1);
			_yTouch = touchEvent.getY(1);
    	} else if (event == TouchEvent.MOVE && touchEvent.isValid())
    	{
			boolean result = scrollImage((touchEvent.getX(1) - _xTouch), (touchEvent.getY(1) - _yTouch));
			
			_xTouch = touchEvent.getX(1);
			_yTouch = touchEvent.getY(1);
			
			//If scrolling occurred, consume the touch event.
			return result;
    	}
    	
    	//The touch event was not consumed.
    	return false;
    }
    
    //Determines if scrolling is required and handles the positioning of the image 
    //when scrolling occurs.  Returns true if the image was scrolled.
    private boolean scrollImage(int xScroll, int yScroll)
    {
        //Get the actual field size from its manager.
        XYRect rect = this.getManager().getContentRect();
        
        //Determine if the image is larger than the field.
        if (rect.width < _theImage.getWidth() || rect.height < _theImage.getHeight())
        {
            //Image is larger than the field.  Enable scrolling support.
            _xCoord -= xScroll;
            _yCoord -= yScroll;
            
            //If the user has scrolled to the end of the image, use the default
            //navigationMovement to allow focus to scroll off the field.
            if (_xCoord < 0  || _yCoord < 0  || ((_theImage.getWidth() - _xCoord) < rect.width) || ((_theImage.getHeight() - _yCoord) < rect.height))
            {
                //Ensure the coordinates do not go lower than 0.
                if (_xCoord < 0) {_xCoord = 0;}
                if (_yCoord < 0) {_yCoord = 0;}
                
                //Ensure that we don't scroll beyond the image size (causing white space to be drawn).
                if ((_theImage.getWidth() - _xCoord) < rect.width)
                {
                    _xCoord = _theImage.getWidth() - rect.width;
                }
                
                if ((_theImage.getHeight() - _yCoord) < rect.height)
                {
                    _yCoord = _theImage.getHeight() - rect.height;
                }
                //Scrolling is not required.
                return false;
            } else
            {
                //The image was scrolled and the movement consumed.
                //Redraw the bitmap.
                this.invalidate();
                return true;
            }
        } else
        {
            //Scrolling is not required.
            return false;
        }    	
    }
} 